package org.zz.gmhelper;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.math.BigInteger;
import java.security.KeyPair;

/**
 * SM2密钥对Bean
 *
 * @author Potato
 */
public class SM2KeyPair {
    private final ECPublicKeyParameters publicKey;
    private final ECPrivateKeyParameters privateKey;

    public SM2KeyPair(ECPublicKeyParameters publicKey, BigInteger privateKey) {
        this.publicKey = publicKey;
        this.privateKey = new ECPrivateKeyParameters(privateKey, SM2Util.DOMAIN_PARAMS);
    }

    public static SM2KeyPair fromJson(String jsonStr) {
        JsonObject jo = JsonParser.parseString(jsonStr).getAsJsonObject();
        String publicKeyStr = jo.get("publicKey").getAsString();
        String privateKeyStr = jo.get("privateKey").getAsString();
        ECPublicKeyParameters point =
                BCECUtil.createECPublicKeyFromStrParameters(
                        publicKeyStr, SM2Util.CURVE, SM2Util.DOMAIN_PARAMS);
        return new SM2KeyPair(point, new BigInteger(privateKeyStr, 16));
    }

    public static ECPublicKeyParameters publicKeyStr2ECPoint(String pubKey) {
        return BCECUtil.createECPublicKeyFromStrParameters(
                pubKey, SM2Util.CURVE, SM2Util.DOMAIN_PARAMS);
    }

    public ECPublicKeyParameters getPublicKey() {
        return publicKey;
    }

    public String getPublicKeyStr() {
        return ByteUtils.toHexString(publicKey.getQ().getEncoded(false));
    }

    public BigInteger getPrivateKey() {
        return privateKey.getD();
    }

    public ECPrivateKeyParameters getPrivateKeyParameter() {
        return privateKey;
    }

    public String toJson() {
        String ret = "{\"publicKey\":\"";
        ret += ByteUtils.toHexString(publicKey.getQ().getEncoded(false));
        ret += "\",\"privateKey\":\"";
        ret += privateKey.getD().toString(16);
        ret += "\"}";
        return ret;
    }

    public String getPrivateKeyStr() {
        return privateKey.getD().toString(16);
    }

    public KeyPair toJavaSecurity() {
        ECDomainParameters domainParams = privateKey.getParameters();
        ECParameterSpec spec =
                new ECParameterSpec(
                        domainParams.getCurve(),
                        domainParams.getG(),
                        domainParams.getN(),
                        domainParams.getH());
        BCECPublicKey bcPublicKey = null;
        BCECPrivateKey bcPrivateKey;
        if (null != publicKey) {
            bcPublicKey =
                    new BCECPublicKey(
                            BCECUtil.ALGO_NAME_EC,
                            publicKey,
                            spec,
                            BouncyCastleProvider.CONFIGURATION);
        }
        bcPrivateKey =
                new BCECPrivateKey(
                        BCECUtil.ALGO_NAME_EC,
                        privateKey,
                        bcPublicKey,
                        spec,
                        BouncyCastleProvider.CONFIGURATION);
        return new KeyPair(bcPublicKey, bcPrivateKey);
    }

    public byte[] toX509DEREncoded() {
        return BCECUtil.convertECPublicKeyToX509(publicKey);
    }

}
